#include "FolderUploader.h"
#include <sstream>
#include <stdexcept>
#include <chrono>
#include <iostream>
#include "StaticConfig.h"
#include <StringTool.h>

FolderUploader::FolderUploader(int id) 
    : isRun(false),
    objectId(id)
{

}

FolderUploader::~FolderUploader() 
{
    stopUpload();
}

int FolderUploader::setUploadParams(const FolderUploadParam& conf)
{
    std::lock_guard<std::mutex> lock(mutex);
    if (isRun)
        return -1;

    StaticConfig::mWorkConfig = conf;    
    StaticConfig::root_path_utf8 = StringTool::string2wstring(StaticConfig::mWorkConfig.local_root_path, CP_UTF8);
    return 0;
}

int FolderUploader::startUpload() 
{
    std::lock_guard<std::mutex> lock(mutex);
    
    if (isRun)
        return 0;

    auto cb = [this](int id)
    {
        completedThreads++;
    };

    isRun = true;
    for (size_t i = 0; i < StaticConfig::mWorkConfig.thread_count; ++i) 
    {
        workers.emplace_back(new ThreadUpload(i, cb));// 启动工作线程
    }

    // 启动扫描线程（原uploadThreadFunc改为扫描任务生成器）
    completedThreads = workers.size();
    scanThread = std::thread(&FolderUploader::scanThreadFunc, this);
    
    return 0;
}

int FolderUploader::stopUpload() 
{   
    std::lock_guard<std::mutex> lock(mutex);

    if (!isRun)
        return 0;    

    // 等待所有工作线程结束
    for (auto& it : workers) 
    {
        delete it;
    }
    workers.clear();

    // 等待扫描线程结束
    isRun = false;
    if (scanThread.joinable()) {
        scanThread.join();
    }

    return 0;
}

bool FolderUploader::isUploading() const 
{
    std::lock_guard<std::mutex> lock(mutex);
    return isRun;
}

void FolderUploader::setProgressCallback(ProgressCallback callback) {
    std::lock_guard<std::mutex> lock(mutex);
    progressCallback = callback;
}

void FolderUploader::setCompleteCallback(CompleteCallback callback) {
    std::lock_guard<std::mutex> lock(mutex);
    completeCallback = callback;
}

// 新增：扫描线程函数（生产者）
void FolderUploader::scanThreadFunc() {
    try {
        // 检查文件夹是否存在
        if (!fs::exists(StaticConfig::root_path_utf8) || !fs::is_directory(StaticConfig::root_path_utf8)) {
            if (completeCallback) {
                completeCallback(false, "本地文件夹不存在或不是一个有效的目录");
            }
            isRun = false;
            return;
        }

        // 持续扫描文件并加入队列
        while (isRun)
        {
            auto files = collectFiles(StaticConfig::root_path_utf8, StaticConfig::mWorkConfig.file_suffix_upload);
            if (files.empty()) 
                std::this_thread::sleep_for(std::chrono::milliseconds(100));// 没有文件时短暂休眠                
            else
            {       
                completedThreads = 0;
                auto result = splitVector(files, workers.size());
                for (int i = 0; i < result.size(); i++)
                {
                    workers[i]->setTasks(result[i]);
                }
            }

            while (completedThreads != workers.size())
            {
                if (!isRun)
                    break;

                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                if (progressCallback)
                {                    
                    UpStatInfo tmp;
                    upStatInfo.reset();
                    for (int i = 0; i < workers.size(); i++)
                    {         
                        tmp.reset();
                        workers[i]->getStatInfo(tmp);
                        upStatInfo.fail_count += tmp.fail_count;
                        upStatInfo.total_count += tmp.total_count;
                    }

                    progressCallback(upStatInfo);
                }                    
            }
                
        }
    }
    catch (const std::exception& e) {
        if (completeCallback) {
            completeCallback(false, "扫描过程中发生错误: " + std::string(e.what()));
        }
    }

    printf("[%s]:return ... ", __FUNCTION__);
}

// 辅助函数：检查文件后缀（不区分大小写）
bool FolderUploader::hasTargetExtension(const std::filesystem::path& filePath, const std::string& targetExt) {
    // 如果未指定后缀，则匹配所有文件
    if (targetExt.empty()) {
        return true;
    }

    if (!fs::is_regular_file(filePath)) {
        return false;
    }

    // 获取文件后缀并转换为小写
    std::string ext = filePath.extension().string();
    std::transform(ext.begin(), ext.end(), ext.begin(),
        [](unsigned char c) { return std::tolower(c); });

    // 处理目标后缀（统一转为带点的小写形式）
    std::string lowerTarget = targetExt;
    std::transform(lowerTarget.begin(), lowerTarget.end(), lowerTarget.begin(),
        [](unsigned char c) { return std::tolower(c); });

    if (!lowerTarget.empty() && lowerTarget[0] != '.') {
        lowerTarget = "." + lowerTarget;
    }

    return ext == lowerTarget;
}

// 收集符合条件的文件列表（支持后缀筛选和递归控制）
std::vector<std::filesystem::path> FolderUploader::collectFiles(
    const std::filesystem::path& folderPath,
    const std::string& fileExtension,
    bool recursive
) {
    std::vector<fs::path> fileList;

    if (!fs::exists(folderPath) || !fs::is_directory(folderPath)) {
        return fileList;
    }

    try {
        if (recursive) {
            // 递归遍历所有子目录
            for (const auto& entry : fs::recursive_directory_iterator(folderPath)) {
                // 检查是否需要停止
                if (!isRun) {
                    return {};
                }

                if (hasTargetExtension(entry.path(), fileExtension)) {
                    fileList.push_back(entry.path());
                }
            }
        }
        else {
            // 仅遍历当前目录
            for (const auto& entry : fs::directory_iterator(folderPath)) {
                if (!isRun) {
                    return {};
                }

                if (hasTargetExtension(entry.path(), fileExtension)) {
                    fileList.push_back(entry.path());
                }
            }
        }
    }
    catch (const fs::filesystem_error& e) {
        std::cerr << "文件遍历错误: " << e.what() << std::endl;
    }

    return fileList;
}